// 将示例代码封装在一个函数中
pub fn run_examples() {
  println!("===== Rust 定长数组示例 =====\n");

  // 1. 数组类型定义
  println!("1. 数组类型定义:");
  example_1();

  // 2. 数组内多个元素作为同一个初始值填充
  println!("\n2. 数组内多个元素作为同一个初始值填充:");
  example_2();

  // 3. 小心越界 panic
  println!("\n3. 小心越界 panic:");
  example_3();

  // 4. 数组切片
  println!("\n4. 数组切片:");
  example_4();
}

// 1. 数组类型定义
fn example_1() {
  let arr: [i32; 5] = [1, 2, 3, 4, 5];
  println!("    数组的类型是 [T; Length], 其长度是类型签名的一部分, 必须在编译期就已知");
  println!("    数组中的所有元素必须是同一类型, 且数组的下标索引从 0 开始.");
  println!("    如 let arr: [i32; 5] = [1, 2, 3, 4, 5]; // 全都是 int32 类型");
  println!("    arr.len(); // {}", arr.len());
}


// 2. 数组内多个元素作为同一个初始值填充
fn example_2() {
  let arr = [1; 100];

  println!("    如 let arr = [1; 100];");
  println!("    arr.len(); // {}", arr.len());
  println!("    arr[0] == 1; // {}", arr[0] == 1);
  println!("    arr[99] == 1; // {}", arr[99] == 1);
}

// 3. 小心越界 panic
fn example_3() {
  let arr = [1; 100];
    
  // `get` 返回 `Option<T>` 类型，因此它的使用非常安全
  let val1 = arr.get(0).unwrap();

  // 但是下标索引就存在越界的风险了
  let val2 = arr[99];
  println!("    如 let arr = [1; 100];");
  println!("    let val1 = arr.get(0).unwrap(); // val1 = {}. `get` 返回 `Option<T>` 类型，因此它的使用非常安全", val1);
  println!("    let val2 = arr[100]; // panic! 下标溢出会直接 panic, 不能这么写");
  println!("    let val2 = arr[99]; // val2 = {}", val2);
}

// 4. 数组切片
fn example_4() {
  let arr: [i32; 5] = [1, 2, 3, 4, 5];
  let slice: &[i32] = &arr[1..4];
  let slice1: &[i32] = &arr[..4];
  println!("    如 let arr: [i32; 5] = [1, 2, 3, 4, 5];");
  println!("    let slice: &[i32] = &arr[1..4]; // 切片是左开右闭的");
  println!("    slice[0]; // {}", slice[0]);
  println!("    let slice1: &[i32] = &arr[..4]; // 还可以省略左侧代表 0, 省略右侧代表总长度.");
  println!("    slice1[0]; // {}", slice1[0]);
}